package ga;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.LinkedList;
import java.util.Set;

import model.Filter;
import model.MethodDeclared;
import model.TestClusterBuilder;
import model.ConstructorDeclared;
import operations.Operation;
import operations.InvokeMethod;
import operations.CreateObject;
import operations.AssignConstant;
import operations.OperationInformation;
import util.Randomness;
import util.GAConfig;
public class Individual implements Comparable{
	private  List<Operation> statements;
	private List<Operation> initialConstructors;
	private  float fitness = 0;
	private  float branchDistance=0;
	public Individual(List<Operation>initialConstructors,List<Operation> statements) {
		this.statements = statements;
		this.initialConstructors=initialConstructors;
	}
	public List<Operation> getInitialConstructors() {
		return initialConstructors;
	}
	public List<Operation> getStatements() {
		return statements;
	}

	public float getFitness() {
		return fitness;
	}
	
	public void setFitness(float fitness) {
		this.fitness = fitness;
	}
	public float getBranchDistance() {
		return branchDistance;
	}
	
	public void setBranchDistance(float branchDistance) {
		this.branchDistance = branchDistance;
	}
	public int getSize() {
		return this.statements.size();
	}
	
	@Override
	public String toString() {
		 StringBuilder initialCons = new StringBuilder();
		 StringBuilder peimitiveCons = new StringBuilder();
		  StringBuilder sb = new StringBuilder();
		  for(Operation cons : this.getInitialConstructors()) {
			  
			  initialCons.append("  ").append(cons.toString()).append(" ");
			  Iterator<OperationInformation> infos = cons.getInfos();
			  if(infos==null){
				  initialCons.append("\n");
				  continue;
			  }
				while(infos.hasNext())
					initialCons.append("  //").append(infos.next().toString()).append("\n");

		  }
			for(Operation op : this.getStatements()) {
				sb.append("  ").append(op.toString()).append(" ");
				Iterator<OperationInformation> infos = op.getInfos();
				if(infos==null) {
					sb.append("\n"); continue;
					}
				while(infos.hasNext())
					sb.append("  //").append(infos.next().toString()).append("\n");

			}
//			tests.append(this.getStatements().toString());
	      return initialCons.toString()+ "\n"+ peimitiveCons.toString() + "\n "+ sb.toString();

	}
	@Override
	public Individual clone() {
		List<Operation> initialConstructors = new LinkedList<Operation>();	
		if(this.initialConstructors.size()!=0)
			for (int i = 0; i < this.initialConstructors.size(); i++)
				initialConstructors.add( (Operation) this.initialConstructors.get(i).clone());

		List<Operation> ops = new LinkedList<Operation>();		
		for (int i = 0; i < this.statements.size(); i++)
			ops.add( (Operation) this.statements.get(i).clone());

		return new Individual(initialConstructors, ops);
	}
	
	public int compareTo(Object o) {
		Individual id = (Individual) o;
	try {

		if(fitness!=0)
			return java.lang.Float.compare(id.getFitness(), fitness);
		if(id.getFitness()!=0)
			return java.lang.Float.compare(id.getFitness(), fitness);
		return java.lang.Float.compare(id.getSize(), this.statements.size());
		} catch (Throwable e) {
			System.err.println("Individual.compareTo: " + e.getMessage());
		}
		return java.lang.Float.compare(id.getSize(), this.statements.size());

	}

	public static void main(String[] args) {
		Randomness.reset(20);
		int size=25;
		 Set<Class<?>> allClasses = new LinkedHashSet<Class<?>>();
	      //get class from file
	      allClasses.addAll(TestClusterBuilder.readClassFromFile());

	      
	      TestClusterBuilder TestCluster = new TestClusterBuilder(allClasses);

	      List<Operation> initialConstructors= Operation.randomGenerateInitialConstructors(TestCluster);
	      List<Operation> ops=new LinkedList<Operation>();
	      ops.addAll(Operation.randomlyGenerateOperation(TestCluster,5));

	      Individual individual=new Individual(initialConstructors,ops);
    	  System.out.println(individual.toString());
    	  individual.setBranchDistance(1);
    	  individual.setFitness(1);
      	  System.out.println("---------- clone -----------");
    	  Individual individual2=individual.clone();
          System.out.println(individual2.toString());
       	
          
          
        System.exit(0);

	}
}
